package org.rency.common.memcache.support.annotation.advice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import javax.annotation.Resource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.rency.common.memcache.service.MemcachedService;
import org.rency.common.memcache.support.annotation.MCacheDomain;
import org.rency.common.memcache.support.annotation.MCacheResult;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(1000)
public class MCacheResultAdvice<T> extends MCacheAdviceBase {
	
	@Resource(name="memcachedService")
	private MemcachedService memcacheService;

	@Pointcut("@annotation(org.rency.common.memcache.support.annotation.MCacheResult)")
    private void cacheResult() {}
	
	@SuppressWarnings("unchecked")
	@Around("cacheResult()")
	public Object aroundCacheResult(ProceedingJoinPoint pjp) throws Throwable {
		long startTime = System.currentTimeMillis();
		T ret = null;
		MCacheDomain domain = null;
		
		try {
            Method currentMethod = getCurrentMethod(pjp);
            Annotation annotation = getMethodAnnotation(currentMethod, MCacheResult.class);
            domain = buildCacheKey(pjp, currentMethod, annotation);
            if(domain == null){
            	throw new RuntimeException("cache annotation error !");
            }
        } catch (Throwable t) {
        	logger.warn("cache aop inner error！", t);
        }
		Object resp = null;
		try {
			resp = memcacheService.getData(domain);
			if(resp == null){
				ret = (T) pjp.proceed();
				if (ret != null) {
					domain.setCacheData(ret);
					memcacheService.setData(domain);
	            }
			}else{
				ret = (T) resp;
			}
		} catch (Throwable t) {
         	logger.warn("cache aop inner error，can not cache data！", t);
        }finally{
        	long endTime = System.currentTimeMillis();
     		logger.info("get cache data use :{}ms, key:{}", (endTime - startTime), domain.getCacheKey()); 
        }
		return ret;
	}
	
}
